//和网络中客户端发送来数据/服务器收包有关

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/time.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <pthread.h>

#include "configure.h"
#include "macro.h"
#include "global.h"
#include "function.h"
#include "mysocket.h"
#include "mymemory.h"
//#include "lock_mutex.h"

//来数据时的处理函数
void MySocket::ReadRequestHandler(lpconnection_t connect) {
	
	bool isflood = false;

	ssize_t reco = RecvProc(connect, connect->recv_buf, connect->recv_len);

	//LogStderr(0, "收到的数据长度为:%d!", reco);
	if(reco <=0) {
		return;
	}
	if(connect->current_stat == _PKG_HD_INIT) {
		if(reco == pkg_head_len_) {
			WaitRequestHandlerProcHead(connect, isflood);
		}
		else {
			connect->current_stat = _PKG_HD_RECVING;
			connect->recv_buf = connect->recv_buf + reco;
			connect->recv_len = connect->recv_len - reco;
		}
	}
	else if(connect->current_stat == _PKG_HD_RECVING) {
		if(reco == connect->recv_len) {
			WaitRequestHandlerProcHead(connect, isflood);
		}
		else {
			connect->recv_buf = connect->recv_buf + reco;
			connect->recv_len = connect->recv_len - reco;
		}
	}
	else if(connect->current_stat == _PKG_BD_INIT) {
		if(connect->recv_len == reco) {
			if(flood_attack_enable_ == 1) {
				isflood = TestFlood(connect);
			}
			WaitRequestHandlerProcBody(connect, isflood);
		}
		else {
			connect->current_stat = _PKG_BD_RECVING;
			connect->recv_buf = connect->recv_buf + reco;
			connect->recv_len = connect->recv_len - reco;
		}
	}
	else if(connect->current_stat == _PKG_BD_RECVING) {
		if(connect->recv_len == reco) {
			if(flood_attack_enable_ == 1) {
				isflood = TestFlood(connect);
			}
			WaitRequestHandlerProcBody(connect, isflood);
		}
		else {
			connect->recv_buf = connect->recv_buf + reco;
			connect->recv_len = connect->recv_len - reco;
		}
	}
	else {
		LogStderr(0, "初始化错误！");
	}

	if(isflood == true) {
		ActiveCloseSocketProc(connect);
	}
	return;
	
}


//接收数据专用函数
ssize_t MySocket::RecvProc(lpconnection_t connect, char *buff, ssize_t buf_len) {
	ssize_t n;
	n = recv(connect->fd, buff, buf_len, 0);
	//LogStderr(0, "收到的数据为%d!", n);
	if(n == 0) {
		//表示客户端连接关闭，收到的为四次挥手的信号
		ActiveCloseSocketProc(connect);
		return -1;
	}


	if(n < 0) {
		//没有收到数据
		if(errno == EAGAIN || errno == EWOULDBLOCK) {
			LogStderr(errno, "MySocket::RecvProc()中errno == EAGAIN || errno == EWOULDBLOCK成立.");
			return -1;
		}
		if(errno == EINTR) {
			//???
			LogStderr(errno, "MySocket::RecvProc()中errno == EINTR成立.");
			return -1;
		}

		if(errno == ECONNRESET) {
			
		}
		else {
			if(errno == EBADF) {
				
			}
			else {
				LogStderr(errno, "MySocket::RecvProc()中发生错误.");
			}
		}
		ActiveCloseSocketProc(connect);
		return -1;
	}
	return n;
}

//包头收整完后的处理
void MySocket::WaitRequestHandlerProcHead(lpconnection_t connect, bool &isflood) {
	//LogStderr(0, "包头收完毕");
	MyMemory *memory = MyMemory::GetInstance();
	LPCOMM_PKG_HEADER pkg_header;
	pkg_header = (LPCOMM_PKG_HEADER)connect->data_head_info;

	unsigned short pkg_len;
	pkg_len = ntohs(pkg_header->pkg_len);

	if(pkg_len < pkg_head_len_) {
		//判断为恶意包或错包
		connect->current_stat = _PKG_HD_INIT;
		connect->recv_buf = connect->data_head_info;
		connect->recv_len = pkg_head_len_;
		//LogStderr(0, "判断为恶意包，丢弃!");
	}

	else if(pkg_len > (_PKG_MAX_LENGTH - 1000)) {
		//恶意包
		connect->current_stat = _PKG_HD_INIT;
		connect->recv_buf = connect->data_head_info;
		connect->recv_len = pkg_head_len_;
		//LogStderr(0, "判断为恶意包，丢弃!");
	}
	else {
		//合法包头，分配内存开始收包体
		char *tmp_buf = (char *)memory->AllocMemory(msg_head_len_ + pkg_len,false);
		connect->recv_mem_pointer = tmp_buf;
		//先填写消息头
		LPSTRUC_MSG_HEADER msg_header = (LPSTRUC_MSG_HEADER)tmp_buf;
		msg_header->connect = connect;
		msg_header->current_sequence = connect->current_sequence;
		tmp_buf += msg_head_len_;
		//填写包头
		memcpy(tmp_buf, pkg_header, pkg_head_len_);
		if(pkg_len == pkg_head_len_) {
			//只含有包头
			if(flood_attack_enable_ == 1) {
				isflood = TestFlood(connect);
			}
			WaitRequestHandlerProcBody(connect, isflood);
		}
		else {
			//LogStderr(0, "继续收包体");
			connect->current_stat = _PKG_BD_INIT;
			connect->recv_buf = tmp_buf + pkg_head_len_;
			connect->recv_len = pkg_len - pkg_head_len_;
		}
	}
	return;
}

//收到完整包后的处理
void MySocket::WaitRequestHandlerProcBody(lpconnection_t connect, bool &isflood) {
	//进入消息队列
	if(isflood == false) {
		thread_pool.InMsgRecvQueueAndSignal(connect->recv_mem_pointer);
	}
	else {
		//遭受洪范攻击，进行处理
		MyMemory *memory = MyMemory::GetInstance();
		memory->FreeMemory(connect->recv_mem_pointer);
	}
	
	connect->recv_mem_pointer = NULL;
	connect->current_stat = _PKG_HD_INIT;
	connect->recv_buf = connect->data_head_info;
	connect->recv_len = pkg_head_len_;
	return;
}

//发送数据专用函数
ssize_t MySocket::SendProc(lpconnection_t connect, char *buff, ssize_t size) {
	ssize_t n;
	for(;;) {
		n = send(connect->fd, buff, size, 0);
		if(n>0) {
			return n;
		}

		if(n == 0) {
			return 0;
		}

		if(errno == EAGAIN) {
			return -1;
		}
		if(errno == EINTR) {
			LogStderr(errno, "MySocket::SendProc中send()失败.");
		}
		else {
			return -2;
		}

	}
}

//数据发送时的写处理函数
void MySocket::WriteRequestHandler(lpconnection_t connect) {
	
	/*
	//组装一个完整的包，发给对面，这里就不写le
	//只发送一条简单的信息
	char tmp[] = "这是来自服务端的信息\n";
	connect->send_buf = tmp;
	connect->send_len = sizeof(tmp);
	*/
	//LogStderr(0, "服务端向客户端发送信息");
	MyMemory *memory = MyMemory::GetInstance();

	ssize_t send_size = SendProc(connect, connect->send_buf, connect->send_len);

	if(send_size > 0 && send_size != connect->send_len) {
		//没有发送完全，只发送了部分
		connect->send_buf = connect->send_buf + send_size;
		connect->send_len = connect->send_len - send_size;
		return;
	}
	else if(send_size == -1) {
		LogStderr(errno, "MySocket::WriteRequestHandler()时，if(send_size == -1成立.)");
		return;
	}
	if(send_size > 0 && send_size == connect->send_len) {
		if(EpollOperEvent(connect->fd, EPOLL_CTL_MOD, EPOLLOUT, 1, connect)== -1) {
			LogStderr(errno, "MySocket::WriteRequestHandler()中EpollOperEvent()失败.");
		}
	}
	memory->FreeMemory(connect->send_mem_pointer);
	connect->send_mem_pointer = NULL;
	--connect->throw_send_count;
	//信号量相关
	if(sem_post(&sem_event_send_queue_)== -1) {
		LogStderr(0, "MySocket::WriteRequestHandler()中sem_post(&sem_event_send_queue_)失败.");
	}
	return;
}

//消息处理线程主函数，子类继承重写
void MySocket::ThreadRecvProcFunc(char *msg_buf) {
	return;
}
